home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
os2
/
edm0407s.zip
/
SEMSRC.ZIP
/
SYNC.H
< prev
Wrap
C/C++ Source or Header
|
1996-06-26
|
10KB
|
521 lines
/* -*- C++ -*-
$Author: Eddy_Kim $
$Id: sync.h 1.8 1996/06/21 08:01:45 Eddy_Kim Exp Eddy_Kim $
$Revision: 1.8 $
Copyright 1996
Eddy Kim
Synchronization classes:
mutex, Event semaphores, locks, multiple event/mutex wait,
reader/writer mutex
*/
#ifndef SYNC_H
#define SYNC_H
#define INCL_BASE
#include <os2.h>
#include <iostream.h>
class Semaphore
{
public:
Semaphore(HSEM hSem=0, ULONG udd=0);
Semaphore(const Semaphore& aSem);
virtual ~Semaphore()=0;
HSEM GetHandle() const;
ULONG GetUDD() const;
void SetUDD(ULONG udd);
protected:
SEMRECORD sem_;
HSEM* GetPHSEM(); // return a pointer to the semaphore handle
HSEM GetHSEM() const; // return the semaphore handle
ULONG* GetPUDD(); // return a pointer to user defined data
ULONG GetUDD() const; // return user defined data
private:
};
/*
mutual exclusion class.
When entering an exclusive code region, or using a limited resource,
use the Mutex to prevent others from entering that area.
OS/2 Mutex locks are recursive. Find out the number of recursive locks
are set by QueryOwner in the count variable.
*/
class Mutex: public Semaphore
{
public:
enum Openmode
{
OPEN,
CREATE,
DONTCARE
};
enum Attr
{
SHARED=DC_SEM_SHARED,
PRIVATE=0,
DEFAULTATTR=SHARED
};
enum InitState
{
OWNED=1,
UNOWNED=0,
DEFAULTSTATE=UNOWNED
};
Mutex();
Mutex(HMTX mtx);
Mutex(const Mutex& mtx);
Mutex(string& mtxname,
Openmode mode=DONTCARE,
ULONG attr=DEFAULTATTR,
BOOL32 state=DEFAULTSTATE);
virtual ~Mutex();
APIRET QueryOwner(PPID pid, PTID tid, PULONG count) const;
APIRET Release();
virtual APIRET Request(ULONG timeout=SEM_INDEFINITE_WAIT);
protected:
private:
Mutex operator=(const Mutex& mtx); // don't allow assignment
APIRET Open(string& mtxname);
APIRET Create(string& mtxname, ULONG attr, BOOL32 state);
};
/*
Use this to automatically grab and release a lock in a
code block. Careful when grabbing multiple locks. Deadlock!
example:
{
MutexLock lock(aMutex);
... do some stuff.
} .. automatically release lock.
*/
class MutexLock
{
public:
MutexLock(Mutex& mtx);
MutexLock(Mutex* mtx);
~MutexLock();
protected:
private:
Mutex& mutex;
operator=(const MutexLock&);
};
/*
Event semaphore class.
Used to notify asychronous threads/processes, that an event has occured.
when the semaphore is set (zero) threads can do a blocking Wait()
call, until posted.
*/
class Event: public Semaphore
{
public:
enum Openmode
{
OPEN,
CREATE,
DONTCARE
};
enum Attr
{
SHARED=DC_SEM_SHARED,
PRIVATE=0,
DEFAULTATTR=SHARED
};
enum InitState
{
OWNED=1,
UNOWNED=0,
DEFAULTSTATE=UNOWNED
};
Event();
Event(const Event&);
Event(string& name,
Openmode mode=DONTCARE,
ULONG attr=DEFAULTATTR,
BOOL32 state=DEFAULTSTATE);
virtual ~Event();
APIRET Post(); // causes blocked threads to execute
virtual APIRET Wait(ULONG timeout=SEM_INDEFINITE_WAIT);
APIRET Query(ULONG* postCount);
APIRET Reset(ULONG* postCount=0);// threads that wait on a reset sem, block
protected:
private:
APIRET Open(string& name);
APIRET Create(string& name, ULONG attr, BOOL32 state);
};
#define INLINE inline
INLINE Semaphore::Semaphore(HSEM hSem, ULONG udd)
{
sem_.hsemCur=hSem;
sem_.ulUser=udd;
}
INLINE Semaphore::Semaphore(const Semaphore& aSem)
{
sem_.hsemCur=aSem.GetHSEM();
sem_.ulUser=aSem.GetUDD();
}
INLINE Semaphore::~Semaphore()
{
}
INLINE HSEM Semaphore::GetHandle() const
{
return GetHSEM();
}
INLINE void Semaphore::SetUDD(ULONG udd)
{
*GetPUDD()=udd;
}
INLINE HSEM* Semaphore::GetPHSEM()
{
return &sem_.hsemCur;
}
INLINE HSEM Semaphore::GetHSEM() const
{
return sem_.hsemCur;
}
INLINE ULONG* Semaphore::GetPUDD()
{
return &sem_.ulUser;
}
INLINE ULONG Semaphore::GetUDD() const
{
return sem_.ulUser;
}
/*
Default mutex contructor. Creates a non-named shared semaphore.
*/
INLINE Mutex::Mutex(): Semaphore()
{
APIRET rc=0;
// create an unnamed mutex
rc=DosCreateMutexSem(NULL,(PHMTX)GetPHSEM(),DEFAULTATTR,DEFAULTSTATE);
if (rc!=0)
{
cerr<<"Error"<<endl;
}
}
/*
Construct a mutex object from an already opened or created mutex handle.
It does not take ownership/responsibility for the passed in handle.
*/
INLINE Mutex::Mutex(HMTX mtx): Semaphore((HSEM)mtx)
{
APIRET rc=DosOpenMutexSem(NULL,(PHMTX)GetPHSEM()); // open it so that when the
// object destructs, the correct semantics happen (DosCloseMutexSem).
if (rc!=0)
{
// Error.
cerr<<"Error"<<endl;
}
}
/*
Opens the passed in mutex by the mutex handle.
*/
INLINE Mutex::Mutex(const Mutex& mtx): Semaphore(mtx)
{
APIRET rc;
rc=DosOpenMutexSem(NULL,(PHMTX)GetPHSEM());
if (rc!=0)
{
// Error.
cerr<<"Error"<<endl;
}
}
/*
constructor. Creates or opens a mutex. If the string is 0 length,
it creates a mutex with no name. If string is non-zero, it first attempts
to open the mutex by name, and if that fails, it will create the mutex.
If created by name, it will only be able to be copied by handle.
*/
INLINE Mutex::Mutex(string& mtxname,
Openmode mode,
ULONG attr,
BOOL32 state): Semaphore()
{
APIRET rc=0;
switch (mode)
{
case DONTCARE:
case OPEN:
if ((mode==OPEN) && (mtxname.length()==0))
{
// unnamed semaphore == error
// to open an unnamed, shared semaphore, use the Mutex(HSEM) ctor
// Error.
cerr<<"Error"<<endl;
}
rc=Open(mtxname);
if (rc==0)
break;
if (mode==OPEN)
{
if (rc!=0)
{
// Error.
cerr<<"Error"<<endl;
}
break;
}
case CREATE:
rc=Create(mtxname,attr,state);
if (rc!=0)
{
// Error.
cerr<<"Error"<<endl;
}
break;
default:
// Error.
;
cerr<<"Error"<<endl;
}
}
INLINE Mutex::~Mutex()
{
APIRET rc=DosCloseMutexSem((HMTX)GetHSEM());
if (rc!=0)
{
// Error.
cerr<<"Error"<<endl;
}
}
INLINE APIRET Mutex::QueryOwner(PPID pid, PTID tid, PULONG count) const
{
return DosQueryMutexSem((HMTX)GetHSEM(),pid,tid,count);
}
INLINE APIRET Mutex::Release()
{
return DosReleaseMutexSem((HMTX)GetHSEM());
}
INLINE APIRET Mutex::Request(ULONG timeout)
{
return DosRequestMutexSem((HMTX)GetHSEM(), timeout);
}
INLINE APIRET Mutex::Open(string& mtxname)
{
APIRET rc;
rc=DosOpenMutexSem(mtxname,(PHMTX)GetPHSEM());
return rc;
}
INLINE APIRET Mutex::Create(string& mtxname, ULONG attr, BOOL32 state)
{
APIRET rc;
if (mtxname.length()==0)
{
// create an unnamed mutex
rc=DosCreateMutexSem(NULL,(PHMTX)GetPHSEM(),attr,state);
}
else
{
// create a named mutex
rc=DosCreateMutexSem(mtxname,(PHMTX)GetPHSEM(),attr,state);
}
return rc;
}
//////////////////////////
INLINE MutexLock::MutexLock(Mutex& mtx): mutex(mtx)
{
APIRET rc=mutex.Request();
if (rc!=0)
{
// +++ error
cerr<<"Error"<<endl;
}
}
INLINE MutexLock::MutexLock(Mutex* mtx): mutex(*mtx)
{
APIRET rc=mutex.Request();
if (rc!=0)
{
// +++ error
cerr<<"Error"<<endl;
}
}
INLINE MutexLock::~MutexLock()
{
APIRET rc=mutex.Release();
if (rc!=0)
{
// +++ error
cerr<<"Error"<<endl;
}
}
////////////////////////////
/*
Default ctor. Creates an unnamed, shared, initially set event
semaphore.
*/
INLINE Event::Event(): Semaphore()
{
APIRET rc=0;
rc=DosCreateEventSem(NULL,(PHEV)GetPHSEM(),DEFAULTATTR,DEFAULTSTATE);
if (rc!=0)
{
// error creating event sem
cerr<<"Error"<<endl;
}
}
/*
Copy ctor. opens existing sem.
*/
INLINE Event::Event(const Event& event): Semaphore(event)
{
APIRET rc=0;
rc=DosOpenEventSem(NULL,(PHEV)GetPHSEM());
if (rc!=0)
{
// error
cerr<<"Error"<<endl;
}
}
INLINE Event::Event(string& name, Openmode mode,
ULONG attr, BOOL32 state):
Semaphore()
{
APIRET rc=0;
switch (mode)
{
case DONTCARE:
case OPEN:
if ((mode==OPEN) && (name.length()==0))
{
// error must open a semaphore using a name.
cerr<<"Error"<<endl;
}
rc=Open(name);
if (rc==0)
break;
if (mode==OPEN)
{
if (rc!=0)
{
// +++ log and throw
cerr<<"Error"<<endl;
}
break;
}
case CREATE:
rc=Create(name,attr,state);
if (rc!=0)
{
// +++ log and throw
cerr<<"Error"<<endl;
}
break;
default:
// +++ log and throw
;
cerr<<"Error"<<endl;
}
}
INLINE Event::~Event()
{
APIRET rc=DosCloseEventSem((HEV)GetHSEM());
if (rc!=0)
{
cerr<<"Error"<<endl;
}
}
INLINE APIRET Event::Post()
{
return DosPostEventSem((HEV)GetHSEM());
}
INLINE APIRET Event::Wait(ULONG timeout)
{
return DosWaitEventSem((HEV)GetHSEM(),timeout);
}
INLINE APIRET Event::Query(ULONG* postCount)
{
return DosQueryEventSem((HEV)GetHSEM(),postCount);
}
INLINE APIRET Event::Reset(ULONG* postCount)
{
if (postCount==0)
{
ULONG count;
// ignore the postcount and just reset the sucker.
return DosResetEventSem((HEV)GetHSEM(),&count);
}
else
{
return DosResetEventSem((HEV)GetHSEM(),postCount);
}
}
INLINE APIRET Event::Open(string& name)
{
APIRET rc;
int filerc;
rc=DosOpenEventSem(name,(PHEV)GetPHSEM());
return rc;
}
INLINE APIRET Event::Create(string& name, ULONG attr, BOOL32 state)
{
APIRET rc;
if (name.length()==0)
{
// create unnamed shares semaphore
rc=DosCreateEventSem(NULL,(PHEV)GetPHSEM(),attr,state);
}
else
{
rc=DosCreateEventSem(name,(PHEV)GetPHSEM(),attr,state);
}
return rc;
}
#endif